package br.com.sendleemail.entity.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;

import javax.jdo.PersistenceManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.com.sendleemail.entity.factory.PMF;

import com.google.appengine.api.datastore.Key;

public class GenericDaoJdo<T, PK extends Serializable> {
	/**
	 * Log variable for all child classes. Uses LogFactory.getLog(getClass())
	 * from Commons Logging
	 */
	protected final Logger log = LoggerFactory.getLogger(getClass());
	private Class<T> persistentClass;
	private static final PersistenceManager pm = PMF.get()
			.getPersistenceManager();

	/**
	 * Constructor that takes in a class for easy creation of DAO
	 */
	public GenericDaoJdo(Class<T> persistentClass) {
		this.persistentClass = persistentClass;
	}

	public boolean exists(PK id) {
		T entity = (T) pm.getObjectById(this.persistentClass, id);
		return entity != null;
	}

	public T get(PK id) {
		T entity = (T) pm.getObjectById(this.persistentClass, id);

		if (entity == null) {
			log.warn("Uh oh, '" + this.persistentClass + "' object with id '"
					+ id + "' not found...");
			// throw new
			// ObjectRetrievalFailureException(this.persistentClass.getName());
		}

		return entity;
	}

	public T getByKey(Key id) {
		T entity = (T) pm.getObjectById(this.persistentClass, id);

		if (entity == null) {
			log.warn("Uh oh, '" + this.persistentClass + "' object with id '"
					+ id + "' not found...");
			// throw new ObjectRetrievalFailureException(this.persistentClass,
			// id);
		}

		return entity;
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		// return new ArrayList<T>(pm.(persistentClass));
		final javax.jdo.Query query = pm.newQuery(persistentClass);

		return (List<T>) query.execute();
	}

	@SuppressWarnings("unchecked")
	public List<T> getAllDistinct() {
		Collection result = new LinkedHashSet(getAll());
		return new ArrayList(result);
	}

	public void remove(PK id) {
		pm.deletePersistent(this.get(id));
	}

	public T save(T object) {
		return (T) pm.makePersistent(object);
	}

}